#pragma once
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <cassert>
#include <functional>

class Thread;
class Context
{
public:
    Thread *_this;
    void *_args;

public:
    Context() : _this(nullptr), _args(nullptr)
    {}

    ~Context() {}
};

class Thread
{
public:
    typedef std::function<void *(void *)> func_t;
    const int num = 1024;
public:
    //为每个线程设置一个名字
    Thread(int number)
    {
        char buffer[num];
        snprintf(buffer, sizeof(buffer), "thread[%d]", number);
        _name = buffer;
    }

    //创建线程
    void start(func_t func, void *args = nullptr)
    {
        _func = func;//上层传入的回调方法
        _args = args;//回调方法对应的参数，在这份代码中传入的是Thread类
        Context *ctx = new Context();
        ctx->_this = this;
        ctx->_args = _args;
        int n = pthread_create(&_tid, nullptr, start_routine, ctx);
        assert(n == 0);
        (void)n;
    }

    void join()
    {
        int n = pthread_join(_tid, nullptr);
        assert(n == 0);
        (void)n;
    }

    void *run(void *args)
    {
        //调用上层传入的回调方法
        return _func(args);
    }

    //创建线程时注册的方法，在类内的话只能是静态的，否则会有隐藏的this指针
    static void *start_routine(void *args)
    {
        //静态方法不能访问类内的非静态变量和方法，所以只能创建一个Context类，通过这个类来访问
        Context *ctx = static_cast<Context *>(args);
        void *ret = ctx->_this->run(ctx->_args);
        delete ctx;
        return ret;
    }

    std::string getname() 
    {
        return _name;
    }

    ~Thread()
    {
        //do nothing
    }


private:
    std::string _name;
    pthread_t _tid;
    void *_args;
    func_t _func;
};